home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-06-19 | 18.2 KB | 623 lines |
- package symantec.itools.awt.util;
-
-
- import java.awt.Panel;
- import java.awt.Dimension;
- import java.awt.Color;
- import java.awt.Event;
- import java.awt.Font;
- import java.awt.Rectangle;
- import java.awt.Graphics;
- import java.awt.FontMetrics;
- import java.awt.Container;
- import java.util.Date;
- import symantec.itools.awt.ComboBox;
- import symantec.itools.awt.NumericSpinner;
-
- // 01/29/97 TWB Integrated changes from Windows
- // 01/30/07 RKM Changed invalidates to repaint
- // Changed logic in paint
- // 1)sc.setBackground is called, only if the colors are different
- // 2)sc.paint is called instead of repaint
- // Made setDate actually work
-
- /**
- * Calendar component. Creates a graphic calendar displaying a month of dates.
- * A combo box controls the month displayed, a numeric spin control changes the
- * year displayed.
- *
- *
- * @version 1.0, Nov 26, 1996
- *
- * @author Symantec
- *
- */
-
-
- public class Calendar
- extends Panel
- {
- private ComboBox combo;
- private boolean bNeedsPlatformHelp;
- private NumericSpinner sc;
- private Date dCurrent;
- private Date dLast;
- private Color selectedColor;
- private String cal[][];
- private int dateSelectedx = -1;
- private int dateSelectedy = -1;
- private int lastSelectedDate = -1;
- private int maxMonthx = -1;
- private int maxMonthy = -1;
- private int firstDay = -1;
- private int topRow = -1;
- private int selectHeight = -1;
- private int centerNumber = -1;
- private int heightAdjust = -1;
- private int numberAdjust = -1;
-
- /**
- * Creates a default calendar with today's
- * date initialized.
- */
- public Calendar()
- {
- this(new Date());
- }
-
- /**
- * Creates a calendar with the specified date initialized.
- * @param defaultdate the date to be shown initially
- */
- public Calendar(Date defaultdate)
- {
- setLayout(null);
- bNeedsPlatformHelp = ComboBox.needsPlatformHelp(); // help comboBar change state
-
- dCurrent = defaultdate;
- dLast = dCurrent;
- combo = new ComboBox();
- combo.addItem("January");
- combo.addItem("February");
- combo.addItem("March");
- combo.addItem("April");
- combo.addItem("May");
- combo.addItem("June");
- combo.addItem("July");
- combo.addItem("August");
- combo.addItem("September");
- combo.addItem("October");
- combo.addItem("November");
- combo.addItem("December");
- add(combo);
- sc = new NumericSpinner();
- add(sc);
- sc.setMin(1900);
- sc.setMax(9999);
- sc.setCurrent(1900 + dCurrent.getYear());
- sc.setEditable(false);
-
- combo.select(dCurrent.getMonth());
- if (symantec.itools.lang.OS.isMacintosh())
- selectedColor = Color.black;
- else
- selectedColor = Color.blue;
-
- if (!symantec.itools.lang.OS.isMacintosh()) //12/18/96 Andy McFarland some platforms don't want their fonts hardwired...
- {
- if (bNeedsPlatformHelp) // different fonts to help display problems.
- setFont(new Font("Dialog", Font.PLAIN, 9));
- else
- setFont(new Font("Dialog", Font.BOLD, 10));
- }
- }
-
- /**
- * Returns the date that the calendar is set to.
- * @return the current value of the calendar.
- */
- public String getDate()
- {
- return dCurrent.toString();
- }
-
- /**
- * Sets the date selected on the calendar.
- * @param date the date that the calendar is to be set to
- */
- public void setDate(String date)
- {
- //Convert string to Date
- Date newDate;
- try {
- newDate = new Date(date);
- } catch (Exception e) {
- newDate = new Date();
- }
-
- if (!dCurrent.equals(newDate))
- {
- dCurrent = newDate;
-
- combo.select(dCurrent.getMonth());
- sc.setCurrent(1900 + dCurrent.getYear());
-
- //Trigger re calculation
- firstDay = -1;
- lastSelectedDate = -1;
-
- repaint();
- }
- }
-
- /**
- * Returns the color that highlights the selected date on the calendar.
- * @return the current selected color.
- */
- public Color getSelectedColor()
- {
- return selectedColor;
- }
-
- /**
- * Sets the color used to highlight the selected date on the calendar.
- * @param c the color that the selected color is to be set to
- */
- public void setSelectedColor(Color c)
- {
- if (!selectedColor.equals(c))
- {
- selectedColor = c;
-
- repaint();
- }
- }
-
- /**
- * Processes events for this component.
- * This is a standard Java AWT method which gets called by the AWT
- * to handle this component's events. The default handler for
- * components dispatches to one of the following methods as needed:
- * action(), gotFocus(), lostFocus(), keyDown(), keyUp(), mouseEnter(),
- * mouseExit(), mouseMove(), mouseDrag(), mouseDown(), or mouseUp().
- *
- * @param event the event to handle
- * @return true if the event was handled and no further action is needed,
- * false to pass the event to this component's parent
- * @see java.awt.Component#action
- * @see java.awt.Component#gotFocus
- * @see java.awt.Component#lostFocus
- * @see java.awt.Component#keyDown
- * @see java.awt.Component#keyUp
- * @see java.awt.Component#mouseEnter
- * @see java.awt.Component#mouseExit
- * @see java.awt.Component#mouseMove
- * @see java.awt.Component#mouseDrag
- * @see java.awt.Component#mouseDown
- * @see java.awt.Component#mouseUp
- */
- public boolean handleEvent(Event event)
- {
- int topRow = -1;
-
- switch(event.id)
- {
- case Event.MOUSE_DOWN:
- {
- if (bNeedsPlatformHelp) // Solaris machines have different drawing levels
- {
- topRow = 70;
- centerNumber = 14;
- heightAdjust = 6;
- numberAdjust = 6;
- }
- else
- {
- topRow = 40; // needed for Windows drawing
- centerNumber = 12;
- heightAdjust = 2;
- numberAdjust = 0;
- }
-
- Rectangle r = bounds();
- int blockheight = ((r.height - topRow - 14) / 7); // 7 rows
- int blockwidth = (r.width - 32) / 7; // 7 columns
-
- if ( ((event.x >= 15) && (event.x < r.width - 15)) && // if event in calendar window
- ((event.y >= topRow + blockheight) && (event.y < r.height - 14)))
- {
- dateSelectedx = ((event.x - 16) / blockwidth);
- dateSelectedy = ((event.y - topRow - blockheight) / blockheight);
- repaint();
- firstDay = -1;
- }
- break;
- }
-
- case Event.ACTION_EVENT:
- {
- // ComboBox list items == month type events
- if (event.target instanceof ComboBox)
- {
- int dy = dCurrent.getDate();
- int mo = combo.getSelectedIndex();
- int yr = dCurrent.getYear();
- dCurrent = new Date(yr, mo, dy);
- while (dCurrent.getMonth() != mo)
- {
- dCurrent = new Date(yr, mo, --dy);
- lastSelectedDate = -1;
- }
- firstDay = -1;
- repaint();
- }
-
- // Spin Control list items == year type events
- if (event.target == sc)
- {
- int dy = dCurrent.getDate();
- int mo = dCurrent.getMonth();
- int yr = sc.getCurrent() - 1900;
- dCurrent = new Date(yr, mo, dy);
- while (dCurrent.getMonth() != mo)
- {
- dCurrent = new Date(yr, mo, --dy);
- lastSelectedDate = -1;
- }
- firstDay = -1;
- repaint();
- }
- break;
- }
- }//switch
-
- return super.handleEvent(event);
- }
-
- boolean isLeapYear(int year)
- {
- if (year% 4 == 0 && (year != 2100))
- return true;
- else
- return false;
- }
-
- /**
- * Moves and/or resizes this component.
- * This is a standard Java AWT method which gets called to move and/or
- * resize this component. Components that are in containers with layout
- * managers should not call this method, but rely on the layout manager
- * instead.
- *
- * @param x horizontal position in the parent's coordinate space
- * @param y vertical position in the parent's coordinate space
- * @param width the new width
- * @param height the new height
- */
- public void reshape(int x, int y, int width, int height)
- {
- sc.reshape(width - 100, 7, 100, 30);
- super.reshape(x, y, width, height);
- }
-
- /**
- * Handles redrawing of this component on the screen.
- * This is a standard Java AWT method which gets called by the Java
- * AWT (repaint()) to handle repainting this component on the screen.
- * The graphics context clipping region is set to the bounding rectangle
- * of this component and its <0,0> coordinate is this component's
- * top-left corner.
- * Typically this method paints the background color to clear the
- * component's drawing space, sets graphics context to be the foreground
- * color, and then calls paint() to draw the component.
- *
- * It is overridden here to reduce flicker by eliminating the uneeded
- * clearing of the background.
- *
- * @param g the graphics context
- * @see java.awt.Component#repaint
- * @see #paint
- */
- public void update(Graphics g)
- {
- paint(g);
- }
-
- /**
- * Paints this component using the given graphics context.
- * This is a standard Java AWT method which typically gets called
- * by the AWT to handle painting this component. It paints this component
- * using the given graphics context. The graphics context clipping region
- * is set to the bounding rectangle of this component and its <0,0>
- * coordinate is this component's top-left corner.
- *
- * @param g the graphics context used for painting
- * @see java.awt.Component#repaint
- * @see #update
- */
- public void paint(Graphics g)
- {
- //If the background of the sc is different, set it
- if (!sc.getBackground().equals(getBackground()))
- sc.setBackground(getBackground());
- sc.paint(g);
-
- FontMetrics fm = getFontMetrics(getFont());
-
- Rectangle r = bounds();
-
- if (symantec.itools.lang.OS.isMacintosh()) // Using layout managers might have obviated most
- { // of this coordinate tweaking - Andy
- combo.reshape(12, 10, 100, 20);
- topRow = 40;
- selectHeight = fm.getHeight();
- centerNumber = 14;
- heightAdjust = 2;
- numberAdjust = 0;
- }
- else
- {
- if (bNeedsPlatformHelp)
- { // Solaris parameters
- combo.reshape(12, 20, 100, 34);
- //sc.reshape(r.width - 90, 20, 80, 34);
- topRow = 70;
- selectHeight = fm.getHeight() + 2;
- centerNumber = 14;
- heightAdjust = 6;
- numberAdjust = 6;
- }
- else
- { // windows parameters
- combo.reshape(12, 10, 100, 25);
- topRow = 40;
- selectHeight = fm.getHeight();
- centerNumber = 12;
- heightAdjust = 2;
- numberAdjust = 0;
- }
- }
-
- int blockwidth = (r.width - 32) / 7; // 7 columns
- int blockheight = ((r.height - topRow - 16) / 7); // 7 rows
- int xloc = blockwidth - (fm.stringWidth("S") / 2); //average location in block
- int yloc = topRow + centerNumber;
- if (dateSelectedx < 0)
- {
- // top
- g.setColor(Color.black);
- g.drawLine(15, topRow, r.width-17, topRow);
-
- // bottom
- g.setColor(Color.lightGray);
- g.drawLine(15, topRow + (7 * blockheight), r.width-18, topRow + (7 * blockheight));
- g.setColor(Color.white);
- g.drawLine(16, topRow + 1 + (7 * blockheight), r.width-17, topRow + 1 + (7 * blockheight));
-
- // left
- g.setColor(Color.black);
- g.drawLine(15, topRow, 15, topRow + (7 * blockheight));
-
- // right
- g.setColor(Color.lightGray);
- g.drawLine(r.width-17, topRow, r.width-17, topRow + (7 * blockheight));
- g.setColor(Color.white);
- g.drawLine(r.width-16, topRow, r.width-16, topRow + (7 * blockheight));
-
- // fill box
- if (symantec.itools.lang.OS.isMacintosh()) // Using layout managers might have obviated most
- {
- g.fillRect(16, topRow + (blockheight) , r.width-33, (6 * blockheight) );
- g.setColor(Color.gray);
- g.fillRect(16, topRow+1, r.width-32, blockheight+1 );
- }
- else
- {
- g.fillRect(16, topRow + (blockheight), r.width-33, (6 * blockheight) + 1);
- g.setColor(Color.gray);
- g.fillRect(16, topRow + 1, r.width-32, blockheight-2);
- }
-
- // letters on top
- g.setColor(Color.white);
-
- if (symantec.itools.lang.OS.isMacintosh())
- {
- yloc += (blockheight+1)/2 - fm.getHeight()/2; // Lets have the day labels track resizes
- // in the component like the numbers do...
- g.drawString("S", xloc, yloc - 1);
- xloc = (2 * blockwidth) - (fm.stringWidth("M") / 2);
- g.drawString("M", xloc, yloc - 1);
- xloc = (3 * blockwidth) - (fm.stringWidth("T") / 2);
- g.drawString("T", xloc, yloc - 1);
- xloc = (4 * blockwidth) - (fm.stringWidth("W") / 2);
- g.drawString("W", xloc, yloc - 1);
- xloc = (5 * blockwidth) - (fm.stringWidth("T") / 2);
- g.drawString("T", xloc, yloc - 1);
- xloc = (6 * blockwidth) - (fm.stringWidth("F") / 2);
- g.drawString("F", xloc, yloc - 1);
- xloc = (7 * blockwidth) - (fm.stringWidth("S") / 2);
- g.drawString("S", xloc, yloc - 1);
- }
- else
- {
- g.drawString("S", xloc, yloc - 1);
- xloc = (2 * blockwidth) - (fm.stringWidth("M") / 2);
- g.drawString("M", xloc, yloc - 1);
- xloc = (3 * blockwidth) - (fm.stringWidth("T") / 2);
- g.drawString("T", xloc, yloc - 1);
- xloc = (4 * blockwidth) - (fm.stringWidth("W") / 2);
- g.drawString("W", xloc, yloc - 1);
- xloc = (5 * blockwidth) - (fm.stringWidth("T") / 2);
- g.drawString("T", xloc, yloc - 1);
- xloc = (6 * blockwidth) - (fm.stringWidth("F") / 2);
- g.drawString("F", xloc, yloc - 1);
- xloc = (7 * blockwidth) - (fm.stringWidth("S") / 2);
- g.drawString("S", xloc, yloc - 1);
- }
- }
-
- Date dMonthStart;
- // must be run twice for Solaris
- dMonthStart = new Date(dCurrent.getYear(), dCurrent.getMonth(), 1);
- dMonthStart = new Date(dCurrent.getYear(), dCurrent.getMonth(), 1);
-
- // which date does month begin?
- if (firstDay < 0)
- firstDay = dMonthStart.getDay();
- int initdate = -1;
- int caldate = 1;
- int templastdate = -1;
- int month = dCurrent.getMonth() + 1;
-
- // which date already selected
- if (lastSelectedDate < 1) initdate = dCurrent.getDate();
- else if (dateSelectedx < 0) initdate = lastSelectedDate;
-
- // paint calendar
- g.setColor(Color.black);
-
- calendar:
-
- for (int j = 0; j < 6; j++)
- {
- for (int i = 0; i < 7; i++)
- {
- if ((maxMonthy < dateSelectedy) || (maxMonthy == dateSelectedy && maxMonthx < dateSelectedx))
- { //click after end date
- dateSelectedx = -1;
- dateSelectedy = -1;
- break calendar;
- }
- if (j == 0 && i < firstDay)
- { // click before the start day
- if (dateSelectedx == i && dateSelectedy == j)
- {
- dateSelectedx = -1;
- dateSelectedy = -1;
- break calendar;
- }
- else
- continue;
- }
-
- // calculate where to draw
- xloc = ((i + 1) * blockwidth) - (fm.stringWidth(Integer.toString(caldate)) / 2);
- yloc = topRow + heightAdjust + 4 + numberAdjust + (((j+2) * blockheight) - fm.getHeight());
-
- // draw one digit numbers differently from two diget
- if (dateSelectedx < 0 && initdate != caldate)
- {
- if (caldate < 10)
- g.drawString((Integer.toString(caldate)), xloc , yloc);
- else
- g.drawString(Integer.toString(caldate), xloc , yloc);
- }
- else if (dateSelectedx == i && dateSelectedy == j || initdate == caldate)
- {
- if (dateSelectedx == i && dateSelectedy == j)
- {
- // must be run twice for Solaris
- dCurrent = new Date(dCurrent.getYear(), dCurrent.getMonth(), caldate);
- dCurrent = new Date(dCurrent.getYear(), dCurrent.getMonth(), caldate);
- }
- //draw selected number
- g.setColor(selectedColor);
- if (caldate < 10)
- g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)) + 2, selectHeight);
- else
- g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)), selectHeight);
- g.setColor(Color.white);
- if (caldate < 10)
- g.drawString(Integer.toString(caldate), xloc , yloc);
- else
- g.drawString(Integer.toString(caldate), xloc , yloc);
- templastdate = caldate;
- g.setColor(Color.black);
- }
- else if (caldate == lastSelectedDate)
- { // unselected previously selected number
- g.setColor(Color.white);
- if (caldate < 10)
- g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)) + 2, selectHeight);
- else
- g.fillRect(xloc, yloc - selectHeight + heightAdjust, fm.stringWidth(Integer.toString(caldate)), selectHeight);
- g.setColor(Color.black);
- if (caldate < 10)
- g.drawString(Integer.toString(caldate), xloc , yloc);
- else
- g.drawString(Integer.toString(lastSelectedDate), xloc, yloc);
- lastSelectedDate = -1;
- }
- if (caldate >= 31)
- {
- maxMonthx = i;
- maxMonthy = j;
- break calendar;
- }
- else if ((caldate >= 30) && ((month == 4) || (month == 6) || (month == 9) || (month == 11)))
- {
- maxMonthx = i;
- maxMonthy = j;
- break calendar;
- }
- else if ((caldate >= 29) && (month == 2))
- {
- maxMonthx = i;
- maxMonthy = j;
- break calendar;
- }
- else if ((caldate >= 28) && (month == 2) && (!isLeapYear(dCurrent.getYear())))
- {
- maxMonthx = i;
- maxMonthy = j;
- break calendar;
- }
- caldate++;
- }
- }
-
- if (lastSelectedDate < 0)
- lastSelectedDate = templastdate;
-
- dateSelectedx = -1;
- dateSelectedy = -1;
-
- if (!dLast.equals(dCurrent))
- {
- dLast = dCurrent;
- Container c = getParent();
- if (c != null)
- c.postEvent( new Event(this, Event.ACTION_EVENT, dCurrent) );
- }
- }
-
- /**
- * Returns the recommended dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the recommended size of this component.
- *
- * @return the preferred dimensions for the calender (250 x 200 pixels).
- *
- * @see #minimumSize
- */
- public Dimension preferredSize()
- {
- return (new Dimension(250,200));
- }
-
- /**
- * Returns the minimum dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the minimum size of this component.
- *
- * @return the minimum dimensions needed for the calender (250 x 200 pixels).
- *
- * @see #preferredSize
- */
- public Dimension minimumSize()
- {
- return (new Dimension(250,200));
- }
- }
-